<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>手写apply,call,bind函数</title>
</head>

<body>
    <script>
        // call--原理，给对象挂上当前this函数；用函数执行后面的参数，删除该函数，返回结果
        Function.prototype.myCall = function (context) {
            if (typeof this !== 'function') {
                throw new TypeError('Error')
            }
            var context = context || window;
            context.fn = this;
            var args = [...arguments].slice(1)
            var result = context.fn(...args)
            delete context.fn
            return result
        }

        // apply
        Function.prototype.myApply = function (context = window, args) {
            if (typeof this !== 'function') {
                throw new TypeError('Error')
            }
            let key = Symbol('key')
            context[key] = this;
            let result = context[key](...args);
            delete context[key];
            return result
        }

        function f(a, b) {
            console.log(a, b)
            console.log(this.name)
        }
        let obj = {
            name: '张三'
        }
        f.myApply(obj, [1, 2]);//arguments[1]

        // bind
        Function.prototype.myBind = function (context) {
            console.log('myBind_this', this);

            if (typeof this !== 'function') {
                throw new TypeError('Error')
            }
            var _this = this;
            var args = [...arguments].slice(1) // 获取第二个开始的参数
            return function F() {
                console.log('F_this', this);

                if (this instanceof F) {
                    return new _this(...args, ...arguments)
                }
                return _this.apply(context, args.concat(...arguments))
            }
        }
        function a(a, b, c, d) {
            console.log(this, a, b, c, d);
        }
        var b = { c: 1 }
        var bindFunc = a.myBind(b, 1, 2, 3)
        bindFunc(4)
        var d = new bindFunc(4)
    </script>
</body>

</html>